package com.xianniu.ltc.aspect;

import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.UserStore;
import com.rebuild.core.privileges.bizz.User;
import com.rebuild.core.service.notification.Message;
import com.rebuild.core.support.general.FieldValueHelper;
import com.xianniu.ltc.feign.api.ApiService;
import com.xianniu.ltc.mapper.TProjectMapper;
import com.xianniu.ltc.model.entity.TProjectDTO;
import com.xianniu.ltc.model.entity.TProjectDetailDTO;
import com.xianniu.ltc.model.po.NotificationAddPO;
import com.xianniu.ltc.service.ProjectService;
import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.entity.ReturnT;
import com.xxl.sso.core.user.XxlSsoUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.AfterReturning;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author dingyuxin
 *
 */
@Slf4j
@Aspect
@Component
public class MessageSendAspect {
    @Resource
    private UserStore userStore;
    @Resource
    private ApiService apiService;
    @Resource
    private ProjectService projectService;
    @Resource
    private HttpServletRequest request;
    @Resource
    private TProjectMapper tProjectMapper;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /**
     * 只有发送消息的时候触发
     * com.rebuild.core.service.notification
     */
    @Pointcut("execution(public * com.rebuild.core.service.notification.NotificationService.*(..))")
    public void sendMessage(){}

    /**
     * 前置通知：在连接点之前执行的通知
     * @param joinPoint
     * @throws Throwable
     */
    @Before("sendMessage()")
    @Trace
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        log.info("消息处理切面方法------>MessageSendAspect开始");
        final String sendMark = "send";
        String method = joinPoint.getSignature().getName();
        if(!sendMark.equalsIgnoreCase(method)){
            return;
        }

        Object[] args = joinPoint.getArgs();
        XxlSsoUser xxlUser;
        try {
            // 当前登录用户信息
            xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
            if (Objects.isNull(xxlUser)){
                log.info("当前登录用户信息为空");
                return;
            }
        }catch (Exception e){
            log.info("todo处理");
            return;
        }

        // 当前登录用户的租户信息
        String tenantCode = UserContextHolder.getTenant();
        // 用户携带的token
        String token = UserContextHolder.getToken();
        // 待发送的消息
        JSONObject message = JSONObject.parseObject(JSONObject.toJSONString(args[0]));
        Integer msgType = message.getInteger("type");
        if(Message.TYPE_APPROVAL != msgType){
            log.info("当前消息的类型是{}, 不需要传递", msgType);
            return;
        }
        try {
            threadPoolTaskExecutor.execute(() -> {
                sendMessage(xxlUser, tenantCode, message, token);
            });
        }catch (Exception e){
            log.error("向xianniu_api推送消息-{}失败...{}", message, e.getMessage());
        }
    }

    private void sendMessage(XxlSsoUser xxlUser, String tenantCode, JSONObject message, String token) {
        UserContextHolder.setTenant(tenantCode);
        String relatedRecord = message.getString("relatedRecord");
        // 通过信息相关单据查询项目ID
        TProjectDetailDTO projectDetail = projectService.selectByEntityId(relatedRecord, tenantCode);
        String projectId = "";
        if (Objects.nonNull(projectDetail)) {
            projectId = projectDetail.getProjectId();
        }
        TProjectDTO projectDTO = tProjectMapper.selectById(projectId);
        String projectCode = null;
        if (projectDTO != null){
            projectCode =  projectDTO.getProjectNo();
        }
        Integer entityCode = Integer.parseInt(relatedRecord.substring(0, 3));
        Entity mEntity = MetadataHelper.getEntity(entityCode);
        // 数据值
        String label = FieldValueHelper.getLabel(ID.valueOf(relatedRecord));
        User toUser = userStore.getUser(ID.valueOf(message.getString("toUser")));
        NotificationAddPO addPO = NotificationAddPO.builder(message, tenantCode, xxlUser.getPhone(), mEntity.getName(), toUser.getWorkphone(), projectCode, label);
        log.info("通知消息发送到API-------->{}", JSON.toJSON(addPO));
        try {
            ReturnT result = apiService.notificationAdd(addPO, token);
            log.info("通知消息请求{} 归集结果:{}", addPO, JSONObject.toJSONString(result));
        }catch (Exception e){
            log.info("通知消息请求失败:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    @AfterReturning(returning = "ret",pointcut = "sendMessage()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求，返回内容
        log.info("消息发送完毕 : " + ret);
    }
}